package com.muli.muwai.demo;


import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class InfoTest {

    private final static String nameFrefix = "set";

    public static Object mapConvertBean(Map<String, Object> map, Object obj) {
        /*
         * Class类是反射的入口 一般获得一个Class对象有三种途径 1.类属性方式，如String.class
         * 2.对象的getClass方法加载，如new String().getClass().
         * 3.forName方法加载，如Class.forName("java.lang.String") 用于动态加载 比如加载驱动
         * 这里我传入一个Object对象,所以我用的是第2种
         */
        Class classz = obj.getClass();
        // 得到传入实体类所有的方法(getXxx setXxx ...)
        // Method[] declaredMethods = classz.getDeclaredMethods();

        // 判断map集合参数不能为null
        if (!map.isEmpty()) {
            for (Map.Entry<String, Object> keyValue : map.entrySet()) {
                // 得到map键值
                String propertyName = keyValue.getKey();
                // 得到map-value值
                Object value = keyValue.getValue();
                // 得到回属性名
                Field field = getClassField(classz, propertyName);

                if (field != null) {
                    // 获取属性类型
                    Class<?> fieldType = field.getType();
                    value  = convertValType(value, fieldType);
                    Method method = null;
                    try {
                        // 得到属性set方法名
                        String setMethodName = convertKey(propertyName);
                        //得到方法
                        method = classz.getMethod(setMethodName, field.getType());
                        //判断是否能够执行（这个可以不要）
                        if (!method.isAccessible()) {
                            method.setAccessible(true);
                        }
                        method.invoke(obj, value);
                    } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            }

        }
        return obj;
    }

    /**
     * 注意：转化map集合的key 例如 属性名 xXxx(tNode)类型 Eclipse自动生成get set方法第一个字母是不会大写的
     *
     * @return
     */
    public static String convertKey(String propertyName) {
        // 将属性名第一个字母大写然后进行拼接
        String setMethodName = nameFrefix.concat(propertyName.substring(0, 1).toUpperCase().concat(propertyName.substring(1)));
        return setMethodName;
    }

    /**
     * 得到属性名
     *
     * @param clazz
     *            类
     * @param fieldName
     *            属性名
     * @return
     */
    private static Field getClassField(Class<?> clazz, String fieldName) {
        // 传入类是Object类型或者是null直接return
        if (clazz == null || Object.class.getName().equals(clazz.getName())) {
            return null;
        }
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }

        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null) {// 简单的递归一下
            return getClassField(superClass, fieldName);
        }
        return null;
    }

    /**
     * 将Object类型的值，转换成bean对象属性里对应的类型值
     *
     * @param value  Object对象值
     * @param fieldType 属性的类型
     * @return 转换后的值
     */
    private static Object convertValType(Object value, Class<?> fieldType) {
        Object retVal = null;
        if (Long.class.getName().equals(fieldType.getName()) || long.class.getName().equals(fieldType.getName())) {
            retVal = Long.parseLong(value.toString());
        } else if (Integer.class.getName().equals(fieldType.getName())
                || int.class.getName().equals(fieldType.getName())) {
            retVal = Integer.parseInt(value.toString());
        } else if (Float.class.getName().equals(fieldType.getName())
                || float.class.getName().equals(fieldType.getName())) {
            retVal = Float.parseFloat(value.toString());
        } else if (Double.class.getName().equals(fieldType.getName())
                || double.class.getName().equals(fieldType.getName())) {
            retVal = Double.parseDouble(value.toString());
        } else if (Boolean.class.getName().equals(fieldType.getName())
                || boolean.class.getName().equals(fieldType.getName())) {
            retVal = Boolean.parseBoolean(value.toString());
        } else if (Character.class.getName().equals(fieldType.getName())
                || char.class.getName().equals(fieldType.getName())) {
            retVal = value;
        } else if(Date.class.getName().equals(fieldType.getName())){
            retVal = strConvertDate(value.toString());
        } else if(String.class.getName().equals(fieldType.getName())){
            retVal = value;
        }
        return retVal;
    }


    /**
     * String类型转Date
     * @param
     * @return
     */
    public static Date strConvertDate(String dateStr){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = null;
        try {
            parse = format.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("ttInteger", 123456);
        hashMap.put("ttDouble", 1.1);
        hashMap.put("ttFloat", 1.2);
        hashMap.put("ttChar", new Character('男'));
        hashMap.put("ttBoolean", true);
        hashMap.put("ttLong", 1221121221221L);
        hashMap.put("ttString", "Hello World");
        hashMap.put("ttDate", "2018-08-27");

        if (!hashMap.isEmpty()) {
            Info info = new Info();
            Object mapConvertBean = mapConvertBean(hashMap, info);
            System.out.println(mapConvertBean.toString());
        }

    }
}
